From ac4eddbbc8f3703789573c3024608744bd113ed0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Nov 2014 11:09:59 -0800 Subject: [PATCH] Fix build scripts and double-compiled packages This commit fixes support for build scripts in packages which are compiled for both the host and target architectures. The support was previously hindered by the fact that the build script was always invoked precisely once for the target architecture unconditionally. This adds support for build scripts themselves to depend on build scripts, and everything should "just work" if build scripts respect their environment variables. --- src/cargo/ops/cargo_clean.rs | 4 +- src/cargo/ops/cargo_compile.rs | 40 +++++--- src/cargo/ops/cargo_rustc/context.rs | 34 ++++++- src/cargo/ops/cargo_rustc/custom_build.rs | 29 +++--- src/cargo/ops/cargo_rustc/mod.rs | 106 ++++++++++++++++------ src/cargo/ops/mod.rs | 2 +- src/cargo/util/config.rs | 17 +--- src/doc/build-script.md | 2 +- tests/test_cargo_compile_custom_build.rs | 2 +- tests/test_cargo_cross_compile.rs | 82 +++++++++++++++++ 10 files changed, 240 insertions(+), 78 deletions(-) diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 7b3aa0ae6..4474302ba 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::default::Default; use std::io::fs::{mod, PathExtensions}; use core::{MultiShell, PackageSet}; @@ -50,7 +50,7 @@ pub fn clean(manifest_path: &Path, opts: &mut CleanOptions) -> CargoResult<()> { let pkgs = PackageSet::new([]); let cx = try!(Context::new("compile", &resolve, &srcs, &pkgs, &mut cfg, Layout::at(root.get_absolute_target_dir()), - None, &pkg, HashMap::new())); + None, &pkg, Default::default())); // And finally, clean everything out! for target in pkg.get_targets().iter() { diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index d05685770..1de7a9e50 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -24,6 +24,7 @@ use std::os; use std::collections::HashMap; +use std::default::Default; use core::registry::PackageRegistry; use core::{MultiShell, Source, SourceId, PackageSet, Package, Target, PackageId}; @@ -138,7 +139,7 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions) let ret = { let _p = profile::start("compiling"); - let lib_overrides = try!(scrape_target_config(&config, &user_configs)); + let lib_overrides = try!(scrape_build_config(&config, &user_configs)); try!(ops::compile_targets(env.as_slice(), targets.as_slice(), to_build, &PackageSet::new(packages.as_slice()), @@ -173,25 +174,40 @@ fn source_ids_from_config(configs: &HashMap, }).map(|p| SourceId::for_path(&p)).collect() } -fn scrape_target_config(config: &Config, - configs: &HashMap) - -> CargoResult> { +fn scrape_build_config(config: &Config, + configs: &HashMap) + -> CargoResult { let target = match configs.find_equiv("target") { - None => return Ok(HashMap::new()), + None => return Ok(Default::default()), Some(target) => try!(target.table().chain_error(|| { internal("invalid configuration for the key `target`") })), }; - let triple = config.target().unwrap_or(config.rustc_host()).to_string(); - let target = match target.get(&triple) { - None => return Ok(HashMap::new()), + + let host = try!(scrape_target_config(target, config.rustc_host())); + let target = match config.target() { + Some(triple) => try!(scrape_target_config(target, triple)), + None => host.clone(), + }; + Ok(ops::BuildConfig { host: host, target: target }) +} + +fn scrape_target_config(target: &HashMap, + triple: &str) + -> CargoResult { + let target = match target.get(&triple.to_string()) { + None => return Ok(Default::default()), Some(target) => try!(target.table().chain_error(|| { internal(format!("invalid configuration for the key \ `target.{}`", triple)) })), }; - let mut ret = HashMap::new(); + let mut ret = ops::TargetConfig { + ar: None, + linker: None, + overrides: HashMap::new(), + }; for (k, v) in target.iter() { match k.as_slice() { "ar" | "linker" => { @@ -199,9 +215,9 @@ fn scrape_target_config(config: &Config, internal(format!("invalid configuration for key `{}`", k)) })).ref0().to_string(); if k.as_slice() == "linker" { - config.set_linker(v); + ret.linker = Some(v); } else { - config.set_ar(v); + ret.ar = Some(v); } } lib_name => { @@ -233,7 +249,7 @@ fn scrape_target_config(config: &Config, output.metadata.push((k.to_string(), v.to_string())); } } - ret.insert(lib_name.to_string(), output); + ret.overrides.insert(lib_name.to_string(), output); } } } diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index 5e9207aa9..89e526308 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -7,7 +7,8 @@ use core::{SourceMap, Package, PackageId, PackageSet, Resolve, Target}; use util::{mod, CargoResult, ChainError, internal, Config, profile}; use util::human; -use super::{Kind, KindHost, KindTarget, Compilation, BuildOutput}; +use super::{Kind, KindHost, KindTarget, Compilation, BuildConfig}; +use super::TargetConfig; use super::layout::{Layout, LayoutProxy}; use super::custom_build::BuildState; @@ -34,6 +35,7 @@ pub struct Context<'a, 'b: 'a> { target_dylib: Option<(String, String)>, target_exe: String, requirements: HashMap<(&'a PackageId, &'a str), PlatformRequirement>, + build_config: BuildConfig, } impl<'a, 'b: 'a> Context<'a, 'b> { @@ -41,7 +43,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> { deps: &'a PackageSet, config: &'b Config<'b>, host: Layout, target: Option, root_pkg: &Package, - build_state: HashMap) + build_config: BuildConfig) -> CargoResult> { let (target_dylib, target_exe) = try!(Context::filename_parts(config.target())); @@ -67,7 +69,8 @@ impl<'a, 'b: 'a> Context<'a, 'b> { host_dylib: host_dylib, requirements: HashMap::new(), compilation: Compilation::new(root_pkg), - build_state: Arc::new(BuildState::new(build_state, deps)), + build_state: Arc::new(BuildState::new(build_config.clone(), deps)), + build_config: build_config, }) } @@ -165,8 +168,13 @@ impl<'a, 'b: 'a> Context<'a, 'b> { pub fn get_requirement(&self, pkg: &'a Package, target: &'a Target) -> PlatformRequirement { + let default = if target.get_profile().is_for_host() { + PlatformPlugin + } else { + PlatformTarget + }; self.requirements.get(&(pkg.get_package_id(), target.get_name())) - .map(|a| *a).unwrap_or(PlatformTarget) + .map(|a| *a).unwrap_or(default) } /// Returns the appropriate directory layout for either a plugin or not. @@ -276,6 +284,24 @@ impl<'a, 'b: 'a> Context<'a, 'b> { !target.get_profile().is_test(), } } + + /// Get the user-specified linker for a particular host or target + pub fn linker(&self, kind: Kind) -> Option<&str> { + self.target_config(kind).linker.as_ref().map(|s| s.as_slice()) + } + + /// Get the user-specified `ar` program for a particular host or target + pub fn ar(&self, kind: Kind) -> Option<&str> { + self.target_config(kind).ar.as_ref().map(|s| s.as_slice()) + } + + /// Get the target configuration for a particular host or target + fn target_config(&self, kind: Kind) -> &TargetConfig { + match kind { + KindHost => &self.build_config.host, + KindTarget => &self.build_config.target, + } + } } impl PlatformRequirement { diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index e5d3d7859..342f67e11 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -10,7 +10,7 @@ use util::{CargoResult, CargoError, human}; use util::{internal, ChainError, Require}; use super::job::Work; -use super::{fingerprint, process, KindTarget, KindHost, Context}; +use super::{fingerprint, process, KindTarget, KindHost, Kind, Context}; use util::Freshness; /// Contains the parsed output of a custom build script. @@ -25,16 +25,16 @@ pub struct BuildOutput { } pub struct BuildState { - pub outputs: Mutex>, + pub outputs: Mutex>, } /// Prepares a `Work` that executes the target as a custom build script. -pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) +pub fn prepare(pkg: &Package, target: &Target, kind: Kind, cx: &mut Context) -> CargoResult<(Work, Work, Freshness)> { // TODO: this shouldn't explicitly pass `KindTarget` for the layout, we // may be running a build script for a plugin dependency. let (script_output, old_script_output, build_output, old_build_output) = { - let target = cx.layout(pkg, KindTarget); + let target = cx.layout(pkg, kind); let host = cx.layout(pkg, KindHost); (host.build(pkg), host.proxy().old_build(pkg), @@ -55,7 +55,10 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) .dir_path() .display().to_string())) .env("NUM_JOBS", Some(cx.config.jobs().to_string())) - .env("TARGET", Some(cx.target_triple())) + .env("TARGET", Some(match kind { + KindHost => cx.config.rustc_host(), + KindTarget => cx.target_triple(), + })) .env("DEBUG", Some(profile.get_debug().to_string())) .env("OPT_LEVEL", Some(profile.get_opt_level().to_string())) .env("PROFILE", Some(profile.get_env())); @@ -123,7 +126,8 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) { let build_state = build_state.outputs.lock(); for &(ref name, ref id) in lib_deps.iter() { - for &(ref key, ref value) in (*build_state)[*id].metadata.iter() { + let data = &build_state[(id.clone(), kind)].metadata; + for &(ref key, ref value) in data.iter() { p = p.env(format!("DEP_{}_{}", super::envify(name.as_slice()), super::envify(key.as_slice())).as_slice(), @@ -151,7 +155,7 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) human("build script output was not valid utf-8") })); let build_output = try!(BuildOutput::parse(output, pkg_name.as_slice())); - build_state.outputs.lock().insert(id, build_output); + build_state.outputs.lock().insert((id, kind), build_output); try!(File::create(&script_output.join("output")) .write_str(output).map_err(|e| { @@ -186,7 +190,7 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) let contents = try!(f.read_to_string()); let output = try!(BuildOutput::parse(contents.as_slice(), pkg_name.as_slice())); - build_state.outputs.lock().insert(id, output); + build_state.outputs.lock().insert((id, kind), output); fresh(tx) }; @@ -195,7 +199,7 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) } impl BuildState { - pub fn new(overrides: HashMap, + pub fn new(config: super::BuildConfig, packages: &PackageSet) -> BuildState { let mut sources = HashMap::new(); for package in packages.iter() { @@ -208,8 +212,11 @@ impl BuildState { } } let mut outputs = HashMap::new(); - for (name, output) in overrides.into_iter() { - outputs.insert(sources[name].clone(), output); + for (name, output) in config.host.overrides.into_iter() { + outputs.insert((sources[name].clone(), KindHost), output); + } + for (name, output) in config.target.overrides.into_iter() { + outputs.insert((sources[name].clone(), KindTarget), output); } BuildState { outputs: Mutex::new(outputs) } } diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index ad7ef6890..6c461135e 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -27,9 +27,22 @@ mod job_queue; mod layout; mod links; -#[deriving(PartialEq, Eq)] +#[deriving(PartialEq, Eq, Hash, Show)] pub enum Kind { KindHost, KindTarget } +#[deriving(Default, Clone)] +pub struct BuildConfig { + pub host: TargetConfig, + pub target: TargetConfig, +} + +#[deriving(Clone, Default)] +pub struct TargetConfig { + pub ar: Option, + pub linker: Option, + pub overrides: HashMap, +} + /// Run `rustc` to figure out what its current version string is. /// /// The second element of the tuple returned is the target triple that rustc @@ -76,7 +89,7 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package, deps: &PackageSet, resolve: &'a Resolve, sources: &'a SourceMap, config: &'a Config<'a>, - lib_overrides: HashMap) + build_config: BuildConfig) -> CargoResult { if targets.is_empty() { return Ok(Compilation::new(pkg)) @@ -95,7 +108,7 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package, let mut cx = try!(Context::new(env, resolve, sources, deps, config, host_layout, target_layout, pkg, - lib_overrides)); + build_config)); let mut queue = JobQueue::new(cx.resolve, deps, cx.config); // First ensure that the destination directory exists @@ -170,18 +183,6 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, (Vec::new(), Vec::new(), Vec::new(), Vec::new()); let (mut build_custom, mut run_custom) = (Vec::new(), Vec::new()); for &target in targets.iter() { - if target.get_profile().is_custom_build() { - // Custom build commands that are for libs that are overridden are - // skipped entirely - if pkg.get_manifest().get_links().is_some() && - cx.build_state.outputs.lock().contains_key(pkg.get_package_id()) { - continue - } - let (dirty, fresh, freshness) = - try!(custom_build::prepare(pkg, target, cx)); - run_custom.push((job(dirty, fresh), freshness)); - } - let work = if target.get_profile().is_doc() { let rustdoc = try!(rustdoc(pkg, target, cx)); vec![(rustdoc, KindTarget)] @@ -190,6 +191,7 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, try!(rustc(pkg, target, cx, req)) }; + // Figure out what stage this work will go into let dst = match (target.is_lib(), target.get_profile().is_test(), target.get_profile().is_custom_build()) { @@ -210,6 +212,45 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, }; dst.push((job(dirty, fresh), freshness)); } + + // If this is a custom build command, we need to not only build the + // script but we also need to run it. Note that this is a little nuanced + // because we may need to run the build script multiple times. If the + // package is needed in both a host and target context, we need to run + // it once per context. + if !target.get_profile().is_custom_build() { continue } + let mut kinds = Vec::new(); + let requirement = targets.iter().find(|t| { + !t.get_profile().is_custom_build() && !t.get_profile().is_doc() + }).map(|&other_target| { + cx.get_requirement(pkg, other_target) + }).unwrap_or(PlatformTarget); + match requirement { + PlatformTarget => kinds.push(KindTarget), + PlatformPlugin => kinds.push(KindHost), + PlatformPluginAndTarget => { + kinds.push(KindTarget); + if cx.config.target().is_some() { + kinds.push(KindHost); + } + } + } + let before = run_custom.len(); + for &kind in kinds.iter() { + let key = (pkg.get_package_id().clone(), kind); + if pkg.get_manifest().get_links().is_some() && + cx.build_state.outputs.lock().contains_key(&key) { + continue + } + let (dirty, fresh, freshness) = + try!(custom_build::prepare(pkg, target, kind, cx)); + run_custom.push((job(dirty, fresh), freshness)); + } + + // If no build scripts were run, no need to compile the build script! + if run_custom.len() == before { + dst.pop(); + } } if targets.iter().any(|t| t.get_profile().is_custom_build()) { @@ -342,22 +383,29 @@ fn rustc(package: &Package, target: &Target, // Prepare the native lib state (extra -L and -l flags) let build_state = cx.build_state.clone(); - let mut native_lib_deps = Vec::new(); + let mut native_lib_deps = HashSet::new(); let current_id = package.get_package_id().clone(); let has_custom_build = package.get_targets().iter().any(|t| { t.get_profile().is_custom_build() }); - // FIXME: traverse build dependencies and add -L and -l for an - // transitive build deps. - if !target.get_profile().is_custom_build() { - each_dep(package, cx, |dep| { - if dep.get_manifest().get_links().is_some() || - (*dep.get_package_id() == current_id && has_custom_build) { - native_lib_deps.push(dep.get_package_id().clone()); + if has_custom_build && !target.get_profile().is_custom_build() { + native_lib_deps.insert(current_id.clone()); + } + // Visit dependencies transitively to figure out what our native + // dependencies are (for -L and -l flags). + for &(pkg, _) in cx.dep_targets(package, target).iter() { + each_dep(pkg, cx, |dep| { + let has_custom_build = dep.get_targets().iter().any(|t| { + t.get_profile().is_custom_build() + }); + if has_custom_build { + native_lib_deps.insert(dep.get_package_id().clone()); } }); } + let mut native_lib_deps = native_lib_deps.into_iter().collect::>(); + native_lib_deps.sort(); (proc(desc_tx: Sender) { let mut rustc = rustc; @@ -366,12 +414,12 @@ fn rustc(package: &Package, target: &Target, // arguments are for native libraries, so we process those here. { let build_state = build_state.outputs.lock(); - for id in native_lib_deps.iter() { - let output = &(*build_state)[*id]; + for id in native_lib_deps.into_iter() { + let output = &build_state[(id.clone(), kind)]; for path in output.library_paths.iter() { rustc = rustc.arg("-L").arg(path); } - if *id == current_id { + if id == current_id { for name in output.library_links.iter() { rustc = rustc.arg("-l").arg(name.as_slice()); } @@ -572,10 +620,8 @@ fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package, } cmd = opt(cmd, "--target", "", cx.config.target()); - cmd = opt(cmd, "-C", "ar=", cx.config.ar().as_ref() - .map(|s| s.as_slice())); - cmd = opt(cmd, "-C", "linker=", cx.config.linker().as_ref() - .map(|s| s.as_slice())); + cmd = opt(cmd, "-C", "ar=", cx.ar(kind)); + cmd = opt(cmd, "-C", "linker=", cx.linker(kind)); } return cmd; diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index d65629986..5a083bda1 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -5,7 +5,7 @@ pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind, rustc_ve pub use self::cargo_rustc::{KindTarget, KindHost, Context, LayoutProxy}; pub use self::cargo_rustc::{PlatformRequirement, PlatformTarget}; pub use self::cargo_rustc::{PlatformPlugin, PlatformPluginAndTarget}; -pub use self::cargo_rustc::{BuildOutput}; +pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig}; pub use self::cargo_run::run; pub use self::cargo_new::{new, NewOptions}; pub use self::cargo_doc::{doc, DocOptions}; diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 398cd0898..daeb85f86 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -1,5 +1,5 @@ use std::{fmt, os, mem}; -use std::cell::{RefCell, RefMut, Ref}; +use std::cell::{RefCell, RefMut}; use std::collections::hash_map::{HashMap, Occupied, Vacant}; use std::io::fs::{PathExtensions, File}; use std::string; @@ -17,8 +17,6 @@ pub struct Config<'a> { shell: RefCell<&'a mut MultiShell>, jobs: uint, target: Option, - linker: RefCell>, - ar: RefCell>, rustc_version: string::String, /// The current host and default target of rustc rustc_host: string::String, @@ -42,8 +40,6 @@ impl<'a> Config<'a> { shell: RefCell::new(shell), jobs: jobs.unwrap_or(os::num_cpus()), target: target, - ar: RefCell::new(None), - linker: RefCell::new(None), rustc_version: rustc_version, rustc_host: rustc_host, }) @@ -83,17 +79,6 @@ impl<'a> Config<'a> { self.target.as_ref().map(|t| t.as_slice()) } - pub fn set_ar(&self, ar: string::String) { - *self.ar.borrow_mut() = Some(ar); - } - - pub fn set_linker(&self, linker: string::String) { - *self.linker.borrow_mut() = Some(linker); - } - - pub fn linker(&self) -> Ref> { self.linker.borrow() } - pub fn ar(&self) -> Ref> { self.ar.borrow() } - /// Return the output of `rustc -v verbose` pub fn rustc_version(&self) -> &str { self.rustc_version.as_slice() diff --git a/src/doc/build-script.md b/src/doc/build-script.md index 6480ac2a9..58c1e004e 100644 --- a/src/doc/build-script.md +++ b/src/doc/build-script.md @@ -76,7 +76,7 @@ are interpreted by Cargo and must be of the form `key=value`. Example output: ``` -cargo:rustc-flags=-l static:foo -L /path/to/foo +cargo:rustc-flags=-l foo:static -L /path/to/foo cargo:root=/path/to/foo cargo:libdir=/path/to/foo/lib cargo:include=/path/to/foo/include diff --git a/tests/test_cargo_compile_custom_build.rs b/tests/test_cargo_compile_custom_build.rs index 52211edd3..cd143bc9c 100644 --- a/tests/test_cargo_compile_custom_build.rs +++ b/tests/test_cargo_compile_custom_build.rs @@ -542,7 +542,7 @@ test!(propagation_of_l_flags { {running} `[..]a-[..]build-script-build[..]` {running} `rustc [..] --crate-name a [..]-L bar[..]-L foo[..]` {compiling} foo v0.5.0 (file://[..]) -{running} `rustc [..] --crate-name foo [..] -L bar[..]-L foo[..]` +{running} `rustc [..] --crate-name foo [..] -L bar -L foo` ", compiling = COMPILING, running = RUNNING).as_slice())); }) diff --git a/tests/test_cargo_cross_compile.rs b/tests/test_cargo_cross_compile.rs index 57ed1418c..71aea949b 100644 --- a/tests/test_cargo_cross_compile.rs +++ b/tests/test_cargo_cross_compile.rs @@ -9,6 +9,7 @@ use support::{project, execs, basic_bin_manifest}; use support::{RUNNING, COMPILING, DOCTEST, cargo_dir}; use hamcrest::{assert_that, existing_file}; use cargo::util::process; +use cargo::ops::rustc_version; fn setup() { } @@ -516,3 +517,84 @@ test!(cross_with_a_build_script { dir = p.root().display(), sep = path::SEP).as_slice())); }) +test!(build_script_needed_for_host_and_target { + if disabled() { return } + + let target = alternate(); + let (_, host) = rustc_version().unwrap(); + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + build = 'build.rs' + + [dependencies.d1] + path = "d1" + [build-dependencies.d2] + path = "d2" + "#) + + .file("build.rs", r#" + extern crate d2; + fn main() { d2::d2(); } + "#) + .file("src/main.rs", " + extern crate d1; + fn main() { d1::d1(); } + ") + .file("d1/Cargo.toml", r#" + [package] + name = "d1" + version = "0.0.0" + authors = [] + build = 'build.rs' + "#) + .file("d1/src/lib.rs", " + pub fn d1() {} + ") + .file("d1/build.rs", r#" + use std::os; + fn main() { + let target = os::getenv("TARGET").unwrap(); + println!("cargo:rustc-flags=-L /path/to/{}", target); + } + "#) + .file("d2/Cargo.toml", r#" + [package] + name = "d2" + version = "0.0.0" + authors = [] + + [dependencies.d1] + path = "../d1" + "#) + .file("d2/src/lib.rs", " + extern crate d1; + pub fn d2() { d1::d1(); } + "); + + assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"), + execs().with_status(0) + .with_stdout(format!("\ +{compiling} d1 v0.0.0 (file://{dir}) +{running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}d1-[..]` +{running} `{dir}{sep}target{sep}build{sep}d1-[..]build-script-build` +{running} `{dir}{sep}target{sep}build{sep}d1-[..]build-script-build` +{running} `rustc {dir}{sep}d1{sep}src{sep}lib.rs [..] --target {target} [..] \ + -L /path/to/{target}` +{running} `rustc {dir}{sep}d1{sep}src{sep}lib.rs [..] \ + -L /path/to/{host}` +{compiling} d2 v0.0.0 (file://{dir}) +{running} `rustc {dir}{sep}d2{sep}src{sep}lib.rs [..] \ + -L /path/to/{host}` +{compiling} foo v0.0.0 (file://{dir}) +{running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}foo-[..] \ + -L /path/to/{host}` +{running} `{dir}{sep}target{sep}build{sep}foo-[..]build-script-build` +{running} `rustc {dir}{sep}src{sep}main.rs [..] --target {target} [..] \ + -L /path/to/{target}` +", compiling = COMPILING, running = RUNNING, target = target, host = host, + dir = p.root().display(), sep = path::SEP).as_slice())); +}) -- 2.30.2